﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;

namespace Web.live
{
    /// <summary>
    /// kswss 的摘要说明
    /// </summary>
    public class kswss : IHttpHandler
    {
        //授权ID
        string sn;
        //读取share
        string sharePath = System.Web.HttpContext.Current.Server.MapPath("/live/ks/") + "share.txt";
        //读取CK
        string loginPath = System.Web.HttpContext.Current.Server.MapPath("/live/ks/") + "kslogin.html";
        string logPath = System.Web.HttpContext.Current.Server.MapPath("/live/ks/") + "log.html";//日志
        string ksid;
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            sn = context.Request.Form["sn"];
            ksid = context.Request.Form["liveid"];
            string path = System.Web.HttpContext.Current.Server.MapPath("/live/");
            string filename = path + sn + ".html";
            if (File.Exists(filename))
            {
                //读取注册码
                string json = ReadFile(System.Web.HttpContext.Current.Server.MapPath("/live/") + sn + ".html");
                //去对应的模板授权数据
                try
                {
                    JToken paramJson = JToken.Parse(json);
                    if (paramJson != null)
                    {
                        if (DateTime.Parse(paramJson["data"]["time"].ToString()) >= DateTime.Now)
                        {
                            context.Response.Write(GetKS(context.Request.Form["zbj"], context.Request.Form["login"], ksid));
                        }
                    }
                }
                catch
                {
                    context.Response.Write("授权过期了联系QQ9021616");
                }
            }
            else
            {
                context.Response.Write("无法查询到授权联系QQ9021616");
            }
            context.Response.End();
        }

        public string GetKS(string zbj, string login, string liveStreamId)
        {
            string ps = "<<<KSWSS>" + sn + ">>zbj=" + zbj + ",liveStreamId=" + liveStreamId + ",login=" + login;
            string WebSockToken;
            string dl = "ok";
            string fx = "ok";
            string shareList = "";
            var LiveDetail = new
            {
                operationName = "LiveDetail",
                variables = new { principalId = zbj },
                query = "query LiveDetail($principalId: String) {\n  webLiveDetail(principalId: $principalId) {\n    liveStream\n    feedInfo {\n      pullCycleMillis\n      __typename\n    }\n    watchingInfo {\n      likeCount\n      watchingCount\n      __typename\n    }\n    noticeList {\n      feed\n      options\n      __typename\n    }\n    fastComments\n    commentColors\n    moreRecommendList {\n      user {\n        id\n        avatar\n        name\n        __typename\n      }\n      watchingCount\n      poster\n      coverUrl\n      caption\n      id\n      playUrls {\n        quality\n        url\n        __typename\n      }\n      quality\n      gameInfo {\n        category\n        name\n        pubgSurvival\n        type\n        kingHero\n        __typename\n      }\n      hasRedPack\n      liveGuess\n      expTag\n      __typename\n    }\n    __typename\n  }\n}\n"
            };
            try
            {
                //读取分享列表
                string sharepath = System.Web.HttpContext.Current.Server.MapPath("/live/ks/") + "share.txt";
                string fileText = File.ReadAllText(sharepath, Encoding.UTF8);
                List<string> lines = new List<string>(fileText.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
                int count = lines.Count;
                JObject paramJson;
                if (count > 0)
                {
                    dl = "no";
                    fx = "ok";
                    for (int i = 0; i < lines.Count; i++)
                    {
                        int sjs = int.Parse(LJSheng.Common.RandStr.CreateNumber(1, 0, count));
                        if ((i + sjs) % 2 == 0 && sjs < 8)
                        {
                            shareList = lines[i];
                            WebSockToken = PostKS(LiveDetail, zbj, dl, fx, shareList);
                            paramJson = JsonConvert.DeserializeObject(WebSockToken) as JObject;
                            if (paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"] != null)
                            {
                                liveStreamId = paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"].ToString();
                                WFile(logPath, liveStreamId + ps + "---" + shareList);
                                break;
                            }
                            Thread.Sleep(518);
                        }
                    }
                }

                if (string.IsNullOrEmpty(liveStreamId))
                {
                    //使用登录获取
                    dl = "ok";
                    fx = "no";
                    WebSockToken = PostKS(LiveDetail, zbj, dl, fx);
                    paramJson = JsonConvert.DeserializeObject(WebSockToken) as JObject;
                    if (paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"] != null)
                    {
                        liveStreamId = paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"].ToString();
                        WFile(logPath, "LOGIN=" + liveStreamId + ps);
                    }
                    else
                    {
                        Thread.Sleep(888);
                        //使用其他接口获取 
                        string historyQuery = "{\"operationName\":\"historyQuery\",\"variables\":{},\"query\":\"query historyQuery {\\n historyList {\\n user {\\n id\\n avatar\\n name\\n __typename\\n    }\\n watchingCount\\n poster\\n coverUrl\\n caption\\n id\\n playUrls {\\n quality\\n url\\n __typename\\n    }\\n quality\\n gameInfo {\\n category\\n name\\n pubgSurvival\\n type\\n kingHero\\n __typename\\n    }\\n hasRedPack\\n liveGuess\\n expTag\\n living\\n __typename\\n  }\\n}\\n\"}";
                        dl = "ok";
                        fx = "no";
                        WebSockToken = PostKS(historyQuery, zbj, dl, fx);
                        paramJson = JsonConvert.DeserializeObject(WebSockToken) as JObject;
                        if (paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"] != null)
                        {
                            liveStreamId = paramJson["data"]["historyList"][0]["id"].ToString();
                            WFile(logPath, "other=" + liveStreamId + ps);
                        }
                        else
                        {
                            Thread.Sleep(888);
                            //登录加分享
                            dl = "ok";
                            fx = "ok";
                            WebSockToken = PostKS(LiveDetail, zbj, dl, fx);
                            paramJson = JsonConvert.DeserializeObject(WebSockToken) as JObject;
                            if (paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"] != null)
                            {
                                liveStreamId = paramJson["data"]["webLiveDetail"]["liveStream"]["liveStreamId"].ToString();
                                WFile(logPath, "share+LOGIN=" + liveStreamId + ps);
                            }
                        }
                    }
                }
                Thread.Sleep(198);
                //获取wss
                if (!string.IsNullOrEmpty(liveStreamId))
                {
                    object WebSocketInfoQuery = new
                    {
                        operationName = "WebSocketInfoQuery",
                        variables = new { liveStreamId },
                        query = "query WebSocketInfoQuery($liveStreamId: String) {\n  webSocketInfo(liveStreamId: $liveStreamId) {\n    token\n    webSocketUrls\n    __typename\n  }\n}\n"
                    };
                    WebSockToken = PostKS(WebSocketInfoQuery, zbj, dl, fx, shareList);
                    WebSockToken = WebSockToken.TrimEnd('}') + ",\"liveStreamId\":\"" + liveStreamId + "\",\"sjs\":\"" + randomNum(16) + "_" + LJSheng.Common.LCommon.GetTimeStamp(DateTime.Now) + "\"}}}";
                }
                else
                {
                    WebSockToken = "请先开直播在打开计票器";
                }
            }
            catch (Exception err) { WebSockToken = err.Message; }

            return WebSockToken;
        }

        /// <summary>
        /// 正常请求
        /// </summary>
        /// <param name="obj_model"></param>
        /// <param name="zbj"></param>
        /// <param name="login"></param>
        /// <returns></returns>
        public string PostKS(object obj_model, string zbj, string login = "no", string share = "no", string shareList = "")
        {
            string strValue = "";
            try
            {
                string url = "https://live.kuaishou.com";
                string param = JsonConvert.SerializeObject(obj_model);
                System.Net.HttpWebRequest request;
                request = (System.Net.HttpWebRequest)WebRequest.Create(url + "/m_graphql");
                request.Method = "POST";
                request.Accept = @"*/*";
                request.KeepAlive = true;
                request.ContentType = "application/json";
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36";
                //request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0";
                request.Headers.Add("Origin", url);
                request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.9");
                request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
                //request.Headers.Add("DNT", "1");
                request.Headers.Add("Sec-Fetch-Dest", "empty");
                request.Headers.Add("Sec-Fetch-Mode", "cors");
                request.Headers.Add("Sec-Fetch-Site", "same-origin");
                //request.Headers.Add("needLoginToWatchHD", "1");
                if (share == "ok")
                {
                    if (string.IsNullOrEmpty(shareList))
                    {
                        shareList = "fid=1446124352&cc=share_wxms&followRefer=151&shareMethod=CARD&docId=5&kpn=NEBULA&subBiz=LIVE_STREAM&shareId=230582155344&shareToken=X33m4LtdYOy01yV_A&shareResourceType=LIVESTREAM_OTHER&userId=125393142&shareType=5&shareMode=APP&appType=21&shareObjectId=yPq0JjlgPa8&shareUrlOpened=0&timestamp=1598274742820";
                    }
                    request.Referer = url + "/u/" + zbj + "?" + shareList;
                }
                else
                {
                    request.Referer = url + "/u/" + zbj;
                }
                if (login == "ok")
                {
                    login = ReadFile(loginPath);
                    if (string.IsNullOrEmpty(login))
                    {
                        login = "clientid=3; did=web_49a302f807d447a59490eb7aed0e530f; client_key=65890b29; didv=1598026794967; userId=2062827367; userId=2062827367; Hm_lvt_86a27b7db2c5c0ae37fee4a8a35033ee=1598022984,1598114053,1598257757; kuaishou.live.web_st=ChRrdWFpc2hvdS5saXZlLndlYi5zdBKgAdUxdyulZNpmcXCiAzjAVrfZzeaAB_51k7Yw5HdqutSxwwDPsIqP3hFphDI4fdcmvCKSy0VSyodlJR1wLvx55pURFVGsdlDtlU4hFr52MxYiNF9yNwhXTXRUt1fMlwksIhrgnoU9iieQ4EHmOGzKyJpXaoiKk01KqbEHg3Hd-IthAW-jXHHg1mb58L2H0sA5SXalhMbwQj45RdsFNflas_gaEiTUdhIhLkqeuKi4MmqrjKj9xSIgSS9Oi48TOm9TtzOhmYzCq1hcUOT95wUQ3jfOA32ag4IoBTAB; kuaishou.live.web_ph=05356d90e19a043b134be19c1b5ba19d0eb9; kuaishou.live.bfb1s=477cb0011daca84b36b3a4676857e5a1;";
                    }
                    request.Headers.Add("Cookie", login);
                }
                else
                {
                    //request.Headers.Add("Cookie", "client_key=65890b29; clientid=3; did=web_7568bb05c5adec10c1bd723ca62c3b1b; kuaishou.live.bfb1s=ac5f27b3b62895859c4c1622f49856a4");
                }
                byte[] payload;
                payload = System.Text.Encoding.UTF8.GetBytes(param);
                request.ContentLength = payload.Length;
                Stream writer = request.GetRequestStream();
                writer.Write(payload, 0, payload.Length);
                writer.Close();
                System.Net.HttpWebResponse response;
                response = (HttpWebResponse)request.GetResponse();
                if (response.ContentEncoding.ToLower().Contains("gzip"))
                {
                    strValue = DecompressGzip(response.GetResponseStream());
                }
                else
                {
                    string encoding = response.ContentEncoding;
                    if (encoding == null || encoding.Length < 1)
                    {
                        encoding = "UTF-8"; //默认编码  
                    }
                    StreamReader Reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
                    string StrDate = "";
                    while ((StrDate = Reader.ReadLine()) != null)
                    {
                        strValue += StrDate;
                    }
                }
            }
            catch (Exception e)
            {
                strValue = null;
            }
            return strValue;
        }

        public string randomNum(int length)
        {
            Random rdm = new Random();
            string text = string.Empty;
            string charset = "bjectSymhasOwnProp-0123456789ABCDEFGHIJKLMNQRTUVWXYZ_dfgiklquvxz";

            for (int i = 0; i < length; i++)
            {
                text += charset[(int)Math.Ceiling(35 * rdm.NextDouble())];
            }
            return text;
        }

        /// <summary>
        /// 压缩HTTP数据包
        /// </summary>
        /// <param name="stm"></param>
        /// <returns></returns>
        public string DecompressGzip(Stream stm)
        {
            string strHTML = "";

            GZipStream gzip = new GZipStream(stm, CompressionMode.Decompress);//解压缩
            using (StreamReader reader = new StreamReader(gzip, Encoding.GetEncoding("UTF-8")))//中文编码处理
            {
                strHTML = reader.ReadToEnd();
            }

            return strHTML;
        }


        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string ReadFile(string path)
        {
            string s = "";
            if (File.Exists(path))
            {
                StreamReader myreader = null;
                try
                {
                    myreader = File.OpenText(path);//读取记事本文件
                    s = myreader.ReadToEnd();//从当前位置读取到文件末尾
                }
                catch { s = null; }
                finally
                {
                    if (myreader != null)
                    {
                        myreader.Close();
                        myreader.Dispose();
                    }
                }
            }
            return s;
        }

        /// <summary>
        /// 写入文件
        /// </summary>
        /// <param name="path"></param>
        private void WFile(string path, string str)
        {
            StreamWriter sr = null;
            try
            {
                if (!File.Exists(path))
                {
                    sr = File.CreateText(path);
                    sr.WriteLine(DateTime.Now.ToString());
                }
                else
                {
                    File.AppendAllText(path, DateTime.Now.ToString() + " - " + str + "\r\n");
                }

            }
            catch (Exception err)
            {

            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                    sr.Dispose();
                }
            }
        }
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}